using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;

namespace DOTS.DOD.LESSON5
{
    [BurstCompile]
    [RequireMatchingQueriesForUpdate]
    [UpdateInGroup(typeof(RandomGenerateCubesSystemGroup))]
    public partial struct RandomCubeGenerateSystem : ISystem
    {
        float mTimer;
        int mTotalCubeCount;

        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<RandomCubeGenerator>();
            mTimer = 0f;
            mTotalCubeCount = 0;
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var cubeGenerator = SystemAPI.GetSingleton<RandomCubeGenerator>();
            if (mTotalCubeCount >= cubeGenerator.GenerateTotalCount)
            {
                state.Enabled = false;
                return;
            }

            if (mTimer >= cubeGenerator.PerTime)
            {
                GenerateCube(ref state, cubeGenerator);
                mTimer -= cubeGenerator.PerTime;
            }

            mTimer += SystemAPI.Time.DeltaTime;
        }

        void GenerateCube(ref SystemState state, RandomCubeGenerator cubeGenerator)
        {
            var cubes = CollectionHelper.CreateNativeArray<Entity>(cubeGenerator.GenerateNumPerTick, Allocator.TempJob);
            var ecb = new EntityCommandBuffer(Allocator.TempJob);
            var random = SystemAPI.GetSingletonRW<RandomSingleton>();
            if (cubeGenerator.UseScheduleParallel)
            {
                EntityCommandBuffer.ParallelWriter ecb_parallel = ecb.AsParallelWriter();
                var job = new GenerateCubesWithParallelWriterJob()
                {
                    CubeProtoType = cubeGenerator.CubeProtoType,
                    Cubes = cubes,
                    ECB_Parallel = ecb_parallel,
                    Random = random,
                };
                state.Dependency = job.ScheduleParallel(cubes.Length, 1, state.Dependency);
            }
            else
            {
                var job = new GenerateCubesJob()
                {
                    CubeProtoType = cubeGenerator.CubeProtoType,
                    Cubes = cubes,
                    ECB = ecb,
                    Random = random,
                };
                state.Dependency = job.Schedule(cubes.Length, state.Dependency);
            }

            state.Dependency.Complete();
            ecb.Playback(state.EntityManager);
            mTotalCubeCount += cubeGenerator.GenerateNumPerTick;
            cubes.Dispose();
            ecb.Dispose();
        }
    }
}